# required libraries
library("RStoolbox")
library("raster")
library("rgdal")
library("ggplot2")
library("SDMTools")
library("png")

En este caso se eligieron 2 imágenes cada una con 2 parcelas distintas

# load tif using stack function instead raster
TTC08226_modified.stack <- stack("../6_qgis/output/TTC08226_modified.tif")
class(TTC08226_modified.stack)
[1] "RasterStack"
attr(,"package")
[1] "raster"
TTC08350_modified.stack <- stack("../6_qgis/output/TTC08350_modified.tif")
class(TTC08350_modified.stack)
[1] "RasterStack"
attr(,"package")
[1] "raster"
# load parcela 4
library(rgeos)
rgeos version: 0.3-26, (SVN revision 560)
 GEOS runtime version: 3.6.1-CAPI-1.10.1 r0 
 Linking to sp version: 1.2-5 
 Polygon checking: TRUE 
# ojo cambio de id entre parcela4 y parcela4.df
parcela4.df <- fortify(parcela4) # to plot with ggplot
Regions defined for each Polygons
head(parcela4.df)
parcela4_1 <- subset(parcelas, parcelas@data$id %in% c(7,8))
parcela4_1.df <- fortify(parcela4_1) # to plot with ggplot
Regions defined for each Polygons
parcela4_2 <- subset(parcelas, parcelas@data$id %in% c(5,6))
parcela4_2.df <- fortify(parcela4_1) # to plot with ggplot
Regions defined for each Polygons
# Set all pixels to NA, where bands are 0 (remove black background)
# Check if results are affected
# instead use crop and mask together (ver más adelante)
TTC08226_modified.stack[TTC08226_modified.stack[,] == 0] <- NA
# plot scene using ggRGB (from ggplot and RStoolbox)
ggRGB(TTC08226_modified.stack, r = 1, g = 2, b = 3, maxpixels = 2e+05, stretch="none", geom_raster = TRUE) + 
    geom_path(data = parcela4_1, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    geom_text(data = p4.centroid.df[3:4,], aes(label = c("4.1", "4.2") ,y = y, x = x), colour = "white") +
    coord_equal() +
    theme_bw()
Regions defined for each Polygons

ggsave("figures/parcela4N.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot parcel 4.1 (de norte a sur)

p41 <- subset(parcela4.df, id == 6)
ggRGB(TTC08226_modified.stack, r = 1, g = 2, b = 3) + 
    geom_path(data = p41, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.1") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Plot parcel 4.2

p42 <- subset(parcela4.df, id == 7)
ggRGB(TTC08226_modified.stack, r = 1, g = 2, b = 3) + 
    geom_path(data = p42, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.1") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

# Set all pixels to NA, where bands are 0 (remove black background)
# Check if results are affected
# instead use crop and mask together (ver más adelante)
TTC08350_modified.stack[TTC08350_modified.stack[,] == 0] <- NA
# plot scene using ggRGB (from ggplot and RStoolbox)
ggRGB(TTC08350_modified.stack, r = 1, g = 2, b = 3, maxpixels = 2e+05, stretch="none", geom_raster = TRUE) + 
    geom_path(data = parcela4_2, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    geom_text(data = p4.centroid.df[1:2,], aes(label = c("4.3", "4.4") ,y = y, x = x), colour = "white") +
    coord_equal() +
    theme_bw()
Regions defined for each Polygons

ggsave("figures/parcela4S.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot parcel 4.3

p43 <- subset(parcela4.df, id == 4)
TTC08350_modified.stack[TTC08350_modified.stack[,] == 0] <- NA
ggRGB(TTC08350_modified.stack, r = 1, g = 2, b = 3, maxpixels = 2e+05, stretch="none", geom_raster = TRUE) + 
    geom_path(data = p43, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.1") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

p44 <- subset(parcela4.df, id == 5)
ggRGB(TTC08350_modified.stack, r = 1, g = 2, b = 3) + 
    geom_path(data = p44, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.1") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Extraemos las parcelas

parcela 4N

# crop and mask whole area
TTC08226_modified.stack_p4N <- crop(mask(TTC08226_modified.stack, parcela4_1),parcela4_1)

Crop parcela 4N

# crop parcela 4N 1
parcela41 <- subset(parcelas, parcelas@data$id %in% c(7))
TTC08226_modified.stack_p41 <- crop(mask(TTC08226_modified.stack_p4N, parcela41), parcela41)
# crop parcela 4N 2
parcela42 <- subset(parcelas, parcelas@data$id %in% c(8))
TTC08226_modified.stack_p42 <- crop(mask(TTC08226_modified.stack_p4N, parcela42), parcela42)
 

Plot parcel 4N 1

# cambio de id !! 7 es igual a 6
p41 <- subset(parcela4.df, id == 6)
ggRGB(TTC08226_modified.stack_p41, r = 1, g = 2, b = 3) + 
    geom_path(data = p41, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.1") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_1.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot parcel 4N 2

# cambio de id !! 8 es igual a 7 
p42 <- subset(parcela4.df, id == 7)
ggRGB(TTC08226_modified.stack_p42, r = 1, g = 2, b = 3) + 
    geom_path(data = p42, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.2") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

parcela 4S

# crop and mask whole area
TTC08350_modified.stack_p4S <- crop(mask(TTC08350_modified.stack, parcela4_2),parcela4_2)

crop parcela 4 S

# requires spatialpolygondataframe
# crop parcela 4N 1
parcela43 <- subset(parcelas, parcelas@data$id %in% c(5))
TTC08335_modified.stack_p43 <- crop(mask(TTC08350_modified.stack_p4S, parcela43), parcela43)
# crop parcela 4N 2
parcela44 <- subset(parcelas, parcelas@data$id %in% c(6))
TTC08335_modified.stack_p44 <- crop(mask(TTC08350_modified.stack_p4S, parcela44), parcela44)
 
# cambio de id !! 8 es igual a 7 
p43 <- subset(parcela4.df, id == 4)
ggRGB(TTC08335_modified.stack_p43, r = 1, g = 2, b = 3) + 
    geom_path(data = p43, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.3") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_3.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)
# cambio de id !! 8 es igual a 7 
p44 <- subset(parcela4.df, id == 5)
ggRGB(TTC08335_modified.stack_p44, r = 1, g = 2, b = 3) + 
    geom_path(data = p44, aes(x = long, y = lat, group = group), size = 1, col="#fbae3b") +
    labs(x="", y="", title="Parcela 4.4") +
   # coord_equal(ylim = c(min(p11$lat), max(p11$lat)), xlim= c(min(p11$long), max(p11$long))) +
    theme_bw() + 
    theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_4.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Calculate VIs

p41.VIs <- spectralIndices(TTC08226_modified.stack_p41, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p41.VIs)

p42.VIs <- spectralIndices(TTC08226_modified.stack_p42, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p42.VIs)

p43.VIs <- spectralIndices(TTC08335_modified.stack_p43, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p43.VIs)

p44.VIs <- spectralIndices(TTC08335_modified.stack_p44, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p44.VIs)

Plot VI one by one

NDVI Parcela 4.1

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p41.VIs$NDVI, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.1") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save

ggsave("figures/parcela4_1_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

MSAVI2 Parcela 4.1

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p41.VIs$MSAVI2, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.1") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save

ggsave("figures/parcela4_1_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

GNDVI Parcela 4.1

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p41.VIs$GNDVI, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.1") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela4_1_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

NDVI Parcela 4.2

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p42.VIs$NDVI, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.2") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save

ggsave("figures/parcela4_2_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

MSAVI2 Parcela 4.2

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p42.VIs$MSAVI2, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.2") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

And save

ggsave("figures/parcela4_2_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

GNDVI Parcela 4.2

cols <- colorRampPalette(c("red", "yellow", "lightgreen"))(length(breaks)-1)
ggR(p42.VIs$GNDVI, geom_raster = TRUE) +
  labs(x="", y="", title= "Parcela 4.2") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))

ggsave("figures/parcela4_2_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Again with p4.3

p43.VIs <- spectralIndices(TTC08335_modified.stack_p43, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p43.VIs)

NDVI Parcela 4.3

ggR(p43.VIs$NDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_3_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

MSAVI2 Parcela 4.3

ggR(p43.VIs$MSAVI2, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_3_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

GNDVI Parcela 4.3

ggR(p43.VIs$GNDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_3_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

foo

Again with p4.3

p43.VIs <- spectralIndices(TTC08335_modified.stack_p43, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p43.VIs)

NDVI Parcela 4.3

ggR(p43.VIs$NDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_3_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

MSAVI2 Parcela 4.3

ggR(p43.VIs$MSAVI2, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_3_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

GNDVI Parcela 4.3

ggR(p43.VIs$GNDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.3") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_3_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Again with p4.4

p44.VIs <- spectralIndices(TTC08335_modified.stack_p44, green = 3, red=2, nir =1, indices=c("NDVI", "MSAVI2", "GNDVI"))
breaks <- seq(0, 1, by=0.01)
plot(p43.VIs)

NDVI Parcela 4.4

ggR(p44.VIs$NDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.4") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

ggsave("figures/parcela4_4_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

MSAVI2 Parcela 4.4

ggR(p44.VIs$MSAVI2, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.4") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_4_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

GNDVI Parcela 4.4

ggR(p44.VIs$GNDVI, geom_raster = TRUE) +
  labs(x="", y="", title="Parcela 4.4") +
  scale_fill_gradientn(colours=cols,  na.value=NA) + 
  theme_bw() +
  theme(plot.title = element_text(lineheight=.8, face="bold", vjust=1, hjust = 0.5))  # make title bold and add spac

Save

ggsave("figures/parcela4_4_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Bind indices in a whole dataframe

library(dplyr)
library(plyr) # Tools for Splitting, Applying and Combining Data
raster_to_df <- function(x) {
  stack(as.data.frame(x))
} # convert raster to dataframe
l<- list(p41 = p41.VIs, p42 = p42.VIs, p43 = p43.VIs, p44 = p44.VIs)
l.df <- lapply(X = l, FUN = raster_to_df) # list of data frames
l.df.VIs <- ldply(l.df ,rbind) # Split list, apply function, and return results in a data frame.

Plot NDVI box-plot

l.df.VIs.NDVI <-  subset(l.df.VIs, ind == "NDVI" )
ggplot(l.df.VIs.NDVI) + 
  geom_boxplot(aes(x = .id, y = values, colour=.id)) +
  facet_grid(. ~ ind) +
  theme_bw()

ggsave("figures/boxplot_p41_p42_p43_p44_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot MSAVI2 box-plot

l.df.VIs.MSAVI2 <-  subset(l.df.VIs, ind == "MSAVI2" )
ggplot(l.df.VIs.MSAVI2) + 
  geom_boxplot(aes(x = .id, y = values, colour=.id)) +
  facet_grid(. ~ ind) +
  theme_bw()

ggsave("figures/boxplot_p41_p42_p43_p44_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot GNDVI box-plot

l.df.VIs.GNDVI <-  subset(l.df.VIs, ind == "GNDVI" )
ggplot(l.df.VIs.GNDVI) + 
  geom_boxplot(aes(x = .id, y = values, colour=.id)) +
  facet_grid(. ~ ind) +
  theme_bw()

ggsave("figures/boxplot_p41_p42_p43_p44_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Plot NDVI, GNDVI MSAVI2 histogram

l.df.VIs.NDVI$title <- "NDVI" # fake
ggplot(l.df.VIs.NDVI, aes(x = values, colour=.id)) + 
  geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
  facet_wrap(~title) +
  scale_y_continuous(labels=scales::percent) +
  ylab("relative frequencies") + 
  theme_bw()

ggsave("figures/histo_p41_p42_p43_p44_NDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)
l.df.VIs.MSAVI2$title = "MSAVI2"
ggplot(l.df.VIs.MSAVI2, aes(x = values, colour=.id)) + 
  geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
  facet_wrap(~title) +
  scale_y_continuous(labels=scales::percent) +
  ylab("relative frequencies") + 
  theme_bw()

ggsave("figures/histo_p41_p42_p43_p44_MSAVI2.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)
l.df.VIs.GNDVI$title <- "GNDVI" # fake
ggplot(l.df.VIs.GNDVI, aes(x = values, colour=.id)) + 
  geom_freqpoly(aes( y=(..count..)/sum(..count..)), binwidth = 0.005) +
  facet_wrap(~title) +
  scale_y_continuous(labels=scales::percent) +
  ylab("relative frequencies") + 
  theme_bw()

ggsave("figures/histo_p41_p42_p43_p44_GNDVI.png", 
 plot = last_plot(), # or give ggplot object name as in myPlot,
 width = 5, height = 5, 
 units = "in", # other options c("in", "cm", "mm"), 
 dpi = 300)

Analysis

# save p41 layers
writeRaster(stack(p41.VIs), paste("p41_", names(p41.VIs), sep = ''), bylayer=TRUE, format='GTiff')
writeRaster(stack(p42.VIs), paste("p42_", names(p42.VIs), sep = ''), bylayer=TRUE, format='GTiff')
writeRaster(stack(p43.VIs), paste("p42_", names(p43.VIs), sep = ''), bylayer=TRUE, format='GTiff')
Error in .getGDALtransient(x, filename = filename, options = options,  : 
  filename exists; use overwrite=TRUE
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KYGBge3J9DQojIHJlcXVpcmVkIGxpYnJhcmllcw0KDQpsaWJyYXJ5KCJSU3Rvb2xib3giKQ0KbGlicmFyeSgicmFzdGVyIikNCmxpYnJhcnkoInJnZGFsIikNCmxpYnJhcnkoImdncGxvdDIiKQ0KbGlicmFyeSgiU0RNVG9vbHMiKQ0KbGlicmFyeSgicG5nIikNCg0KYGBgDQoNCkVuIGVzdGUgY2FzbyBzZSBlbGlnaWVyb24gMiBpbcOhZ2VuZXMgY2FkYSB1bmEgY29uIDIgcGFyY2VsYXMgZGlzdGludGFzDQoNCmBgYHtyfQ0KIyBsb2FkIHRpZiB1c2luZyBzdGFjayBmdW5jdGlvbiBpbnN0ZWFkIHJhc3Rlcg0KDQpUVEMwODIyNl9tb2RpZmllZC5zdGFjayA8LSBzdGFjaygiLi4vNl9xZ2lzL291dHB1dC9UVEMwODIyNl9tb2RpZmllZC50aWYiKQ0KY2xhc3MoVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2spDQoNCg0KVFRDMDgzNTBfbW9kaWZpZWQuc3RhY2sgPC0gc3RhY2soIi4uLzZfcWdpcy9vdXRwdXQvVFRDMDgzNTBfbW9kaWZpZWQudGlmIikNCmNsYXNzKFRUQzA4MzUwX21vZGlmaWVkLnN0YWNrKQ0KYGBgDQoNCg0KYGBge3J9DQojIGxvYWQgcGFyY2VsYSA0DQpsaWJyYXJ5KHJnZW9zKQ0KDQpwYXJjZWxhcyA8LSByZWFkT0dSKCIuLi82X3FnaXMvaW5wdXQvYWxhbWFsYS5rbWwiLCAiYWxhbWFsYSIpWzBdDQoNCm5yb3dkaW0gPC0gZGltKHBhcmNlbGFzQGRhdGEpDQpwYXJjZWxhc0BkYXRhJGlkIDwtIGMocmVwKDE6bnJvd2RpbSkpDQoNCiMgNyA4IE4NCiMgNSwgNiBTDQpwYXJjZWxhNCA8LSBzdWJzZXQocGFyY2VsYXMsIHBhcmNlbGFzQGRhdGEkaWQgJWluJSBjKDUsNiwgNywgOCkpDQpwNC5jZW50cm9pZC5kZiA8LSBhcy5kYXRhLmZyYW1lKGdDZW50cm9pZChwYXJjZWxhNCwgYnlpZCA9IFRSVUUpKSAjIGV4dHJhY3QgdG8gbGFiZWwgcGFyY2Vscw0KDQpjbGFzcyhwYXJjZWxhNCkNCnBsb3QocGFyY2VsYTQpDQoNCg0KYGBgDQoNCg0KYGBge3J9DQoNCiMgb2pvIGNhbWJpbyBkZSBpZCBlbnRyZSBwYXJjZWxhNCB5IHBhcmNlbGE0LmRmDQpwYXJjZWxhNC5kZiA8LSBmb3J0aWZ5KHBhcmNlbGE0KSAjIHRvIHBsb3Qgd2l0aCBnZ3Bsb3QNCmhlYWQocGFyY2VsYTQuZGYpDQpgYGANCg0KYGBge3J9DQpwYXJjZWxhNF8xIDwtIHN1YnNldChwYXJjZWxhcywgcGFyY2VsYXNAZGF0YSRpZCAlaW4lIGMoNyw4KSkNCnBhcmNlbGE0XzEuZGYgPC0gZm9ydGlmeShwYXJjZWxhNF8xKSAjIHRvIHBsb3Qgd2l0aCBnZ3Bsb3QNCg0KcGFyY2VsYTRfMiA8LSBzdWJzZXQocGFyY2VsYXMsIHBhcmNlbGFzQGRhdGEkaWQgJWluJSBjKDUsNikpDQpwYXJjZWxhNF8yLmRmIDwtIGZvcnRpZnkocGFyY2VsYTRfMSkgIyB0byBwbG90IHdpdGggZ2dwbG90DQoNCmBgYA0KDQoNCg0KYGBge3J9DQoNCg0KIyBTZXQgYWxsIHBpeGVscyB0byBOQSwgd2hlcmUgYmFuZHMgYXJlIDAgKHJlbW92ZSBibGFjayBiYWNrZ3JvdW5kKQ0KIyBDaGVjayBpZiByZXN1bHRzIGFyZSBhZmZlY3RlZA0KIyBpbnN0ZWFkIHVzZSBjcm9wIGFuZCBtYXNrIHRvZ2V0aGVyICh2ZXIgbcOhcyBhZGVsYW50ZSkNCg0KVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tbVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tbLF0gPT0gMF0gPC0gTkENCg0KDQojIHBsb3Qgc2NlbmUgdXNpbmcgZ2dSR0IgKGZyb20gZ2dwbG90IGFuZCBSU3Rvb2xib3gpDQpnZ1JHQihUVEMwODIyNl9tb2RpZmllZC5zdGFjaywgciA9IDEsIGcgPSAyLCBiID0gMywgbWF4cGl4ZWxzID0gMmUrMDUsIHN0cmV0Y2g9Im5vbmUiLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwYXJjZWxhNF8xLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gcDQuY2VudHJvaWQuZGZbMzo0LF0sIGFlcyhsYWJlbCA9IGMoIjQuMSIsICI0LjIiKSAseSA9IHksIHggPSB4KSwgY29sb3VyID0gIndoaXRlIikgKw0KICAgIGNvb3JkX2VxdWFsKCkgKw0KICAgIHRoZW1lX2J3KCkNCmBgYA0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTROLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpQbG90IHBhcmNlbCA0LjEgKGRlIG5vcnRlIGEgc3VyKQ0KDQpgYGB7cn0NCnA0MSA8LSBzdWJzZXQocGFyY2VsYTQuZGYsIGlkID09IDYpDQoNCmdnUkdCKFRUQzA4MjI2X21vZGlmaWVkLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzKSArIA0KICAgIGdlb21fcGF0aChkYXRhID0gcDQxLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC4xIikgKw0KICAgIyBjb29yZF9lcXVhbCh5bGltID0gYyhtaW4ocDExJGxhdCksIG1heChwMTEkbGF0KSksIHhsaW09IGMobWluKHAxMSRsb25nKSwgbWF4KHAxMSRsb25nKSkpICsNCiAgICB0aGVtZV9idygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKSAgIyBtYWtlIHRpdGxlIGJvbGQgYW5kIGFkZCBzcGFjDQoNCmBgYA0KDQoNCg0KDQpQbG90IHBhcmNlbCA0LjINCg0KYGBge3J9DQpwNDIgPC0gc3Vic2V0KHBhcmNlbGE0LmRmLCBpZCA9PSA3KQ0KDQpnZ1JHQihUVEMwODIyNl9tb2RpZmllZC5zdGFjaywgciA9IDEsIGcgPSAyLCBiID0gMykgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHA0MiwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgc2l6ZSA9IDEsIGNvbD0iI2ZiYWUzYiIpICsNCiAgICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuMSIpICsNCiAgICMgY29vcmRfZXF1YWwoeWxpbSA9IGMobWluKHAxMSRsYXQpLCBtYXgocDExJGxhdCkpLCB4bGltPSBjKG1pbihwMTEkbG9uZyksIG1heChwMTEkbG9uZykpKSArDQogICAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KYGBge3J9DQoNCg0KIyBTZXQgYWxsIHBpeGVscyB0byBOQSwgd2hlcmUgYmFuZHMgYXJlIDAgKHJlbW92ZSBibGFjayBiYWNrZ3JvdW5kKQ0KIyBDaGVjayBpZiByZXN1bHRzIGFyZSBhZmZlY3RlZA0KIyBpbnN0ZWFkIHVzZSBjcm9wIGFuZCBtYXNrIHRvZ2V0aGVyICh2ZXIgbcOhcyBhZGVsYW50ZSkNCg0KVFRDMDgzNTBfbW9kaWZpZWQuc3RhY2tbVFRDMDgzNTBfbW9kaWZpZWQuc3RhY2tbLF0gPT0gMF0gPC0gTkENCg0KDQojIHBsb3Qgc2NlbmUgdXNpbmcgZ2dSR0IgKGZyb20gZ2dwbG90IGFuZCBSU3Rvb2xib3gpDQpnZ1JHQihUVEMwODM1MF9tb2RpZmllZC5zdGFjaywgciA9IDEsIGcgPSAyLCBiID0gMywgbWF4cGl4ZWxzID0gMmUrMDUsIHN0cmV0Y2g9Im5vbmUiLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwYXJjZWxhNF8yLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gcDQuY2VudHJvaWQuZGZbMToyLF0sIGFlcyhsYWJlbCA9IGMoIjQuMyIsICI0LjQiKSAseSA9IHksIHggPSB4KSwgY29sb3VyID0gIndoaXRlIikgKw0KICAgIGNvb3JkX2VxdWFsKCkgKw0KICAgIHRoZW1lX2J3KCkNCmBgYA0KDQoNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRTLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpQbG90IHBhcmNlbCA0LjMNCg0KYGBge3J9DQpwNDMgPC0gc3Vic2V0KHBhcmNlbGE0LmRmLCBpZCA9PSA0KQ0KDQpUVEMwODM1MF9tb2RpZmllZC5zdGFja1tUVEMwODM1MF9tb2RpZmllZC5zdGFja1ssXSA9PSAwXSA8LSBOQQ0KDQoNCmdnUkdCKFRUQzA4MzUwX21vZGlmaWVkLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzLCBtYXhwaXhlbHMgPSAyZSswNSwgc3RyZXRjaD0ibm9uZSIsIGdlb21fcmFzdGVyID0gVFJVRSkgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHA0MywgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgc2l6ZSA9IDEsIGNvbD0iI2ZiYWUzYiIpICsNCiAgICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuMSIpICsNCiAgICMgY29vcmRfZXF1YWwoeWxpbSA9IGMobWluKHAxMSRsYXQpLCBtYXgocDExJGxhdCkpLCB4bGltPSBjKG1pbihwMTEkbG9uZyksIG1heChwMTEkbG9uZykpKSArDQogICAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KDQpgYGB7cn0NCnA0NCA8LSBzdWJzZXQocGFyY2VsYTQuZGYsIGlkID09IDUpDQoNCmdnUkdCKFRUQzA4MzUwX21vZGlmaWVkLnN0YWNrLCByID0gMSwgZyA9IDIsIGIgPSAzKSArIA0KICAgIGdlb21fcGF0aChkYXRhID0gcDQ0LCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBzaXplID0gMSwgY29sPSIjZmJhZTNiIikgKw0KICAgIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC4xIikgKw0KICAgIyBjb29yZF9lcXVhbCh5bGltID0gYyhtaW4ocDExJGxhdCksIG1heChwMTEkbGF0KSksIHhsaW09IGMobWluKHAxMSRsb25nKSwgbWF4KHAxMSRsb25nKSkpICsNCiAgICB0aGVtZV9idygpICsgDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKSAgIyBtYWtlIHRpdGxlIGJvbGQgYW5kIGFkZCBzcGFjDQoNCmBgYA0KDQpFeHRyYWVtb3MgbGFzIHBhcmNlbGFzDQoNCnBhcmNlbGEgNE4NCg0KYGBge3J9DQojIGNyb3AgYW5kIG1hc2sgd2hvbGUgYXJlYQ0KVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tfcDROIDwtIGNyb3AobWFzayhUVEMwODIyNl9tb2RpZmllZC5zdGFjaywgcGFyY2VsYTRfMSkscGFyY2VsYTRfMSkNCg0KYGBgDQoNCkNyb3AgcGFyY2VsYSA0Tg0KDQpgYGB7cn0NCg0KIyByZXF1aXJlcyBzcGF0aWFscG9seWdvbmRhdGFmcmFtZQ0KDQojIGNyb3AgcGFyY2VsYSA0TiAxDQpwYXJjZWxhNDEgPC0gc3Vic2V0KHBhcmNlbGFzLCBwYXJjZWxhc0BkYXRhJGlkICVpbiUgYyg3KSkNCg0KVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tfcDQxIDwtIGNyb3AobWFzayhUVEMwODIyNl9tb2RpZmllZC5zdGFja19wNE4sIHBhcmNlbGE0MSksIHBhcmNlbGE0MSkNCg0KDQojIGNyb3AgcGFyY2VsYSA0TiAyDQoNCnBhcmNlbGE0MiA8LSBzdWJzZXQocGFyY2VsYXMsIHBhcmNlbGFzQGRhdGEkaWQgJWluJSBjKDgpKQ0KVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tfcDQyIDwtIGNyb3AobWFzayhUVEMwODIyNl9tb2RpZmllZC5zdGFja19wNE4sIHBhcmNlbGE0MiksIHBhcmNlbGE0MikNCiANCg0KYGBgDQoNCg0KUGxvdCBwYXJjZWwgNE4gMQ0KDQoNCmBgYHtyfQ0KIyBjYW1iaW8gZGUgaWQgISEgNyBlcyBpZ3VhbCBhIDYNCnA0MSA8LSBzdWJzZXQocGFyY2VsYTQuZGYsIGlkID09IDYpDQoNCmdnUkdCKFRUQzA4MjI2X21vZGlmaWVkLnN0YWNrX3A0MSwgciA9IDEsIGcgPSAyLCBiID0gMykgKyANCiAgICBnZW9tX3BhdGgoZGF0YSA9IHA0MSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgc2l6ZSA9IDEsIGNvbD0iI2ZiYWUzYiIpICsNCiAgICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuMSIpICsNCiAgICMgY29vcmRfZXF1YWwoeWxpbSA9IGMobWluKHAxMSRsYXQpLCBtYXgocDExJGxhdCkpLCB4bGltPSBjKG1pbihwMTEkbG9uZyksIG1heChwMTEkbG9uZykpKSArDQogICAgdGhlbWVfYncoKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfMS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNClBsb3QgcGFyY2VsIDROIDINCg0KDQpgYGB7cn0NCg0KIyBjYW1iaW8gZGUgaWQgISEgOCBlcyBpZ3VhbCBhIDcgDQpwNDIgPC0gc3Vic2V0KHBhcmNlbGE0LmRmLCBpZCA9PSA3KQ0KDQpnZ1JHQihUVEMwODIyNl9tb2RpZmllZC5zdGFja19wNDIsIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwNDIsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSA0LjIiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8yLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpwYXJjZWxhIDRTDQoNCg0KYGBge3J9DQojIGNyb3AgYW5kIG1hc2sgd2hvbGUgYXJlYQ0KVFRDMDgzNTBfbW9kaWZpZWQuc3RhY2tfcDRTIDwtIGNyb3AobWFzayhUVEMwODM1MF9tb2RpZmllZC5zdGFjaywgcGFyY2VsYTRfMikscGFyY2VsYTRfMikNCg0KYGBgDQoNCmNyb3AgcGFyY2VsYSA0IFMNCmBgYHtyfQ0KDQojIHJlcXVpcmVzIHNwYXRpYWxwb2x5Z29uZGF0YWZyYW1lDQoNCiMgY3JvcCBwYXJjZWxhIDROIDENCnBhcmNlbGE0MyA8LSBzdWJzZXQocGFyY2VsYXMsIHBhcmNlbGFzQGRhdGEkaWQgJWluJSBjKDUpKQ0KDQpUVEMwODMzNV9tb2RpZmllZC5zdGFja19wNDMgPC0gY3JvcChtYXNrKFRUQzA4MzUwX21vZGlmaWVkLnN0YWNrX3A0UywgcGFyY2VsYTQzKSwgcGFyY2VsYTQzKQ0KDQoNCiMgY3JvcCBwYXJjZWxhIDROIDINCg0KcGFyY2VsYTQ0IDwtIHN1YnNldChwYXJjZWxhcywgcGFyY2VsYXNAZGF0YSRpZCAlaW4lIGMoNikpDQpUVEMwODMzNV9tb2RpZmllZC5zdGFja19wNDQgPC0gY3JvcChtYXNrKFRUQzA4MzUwX21vZGlmaWVkLnN0YWNrX3A0UywgcGFyY2VsYTQ0KSwgcGFyY2VsYTQ0KQ0KIA0KDQpgYGANCg0KDQpgYGB7cn0NCg0KIyBjYW1iaW8gZGUgaWQgISEgOCBlcyBpZ3VhbCBhIDcgDQpwNDMgPC0gc3Vic2V0KHBhcmNlbGE0LmRmLCBpZCA9PSA0KQ0KDQpnZ1JHQihUVEMwODMzNV9tb2RpZmllZC5zdGFja19wNDMsIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwNDMsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSA0LjMiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgYA0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfMy5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCg0KIyBjYW1iaW8gZGUgaWQgISEgOCBlcyBpZ3VhbCBhIDcgDQpwNDQgPC0gc3Vic2V0KHBhcmNlbGE0LmRmLCBpZCA9PSA1KQ0KDQpnZ1JHQihUVEMwODMzNV9tb2RpZmllZC5zdGFja19wNDQsIHIgPSAxLCBnID0gMiwgYiA9IDMpICsgDQogICAgZ2VvbV9wYXRoKGRhdGEgPSBwNDQsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIHNpemUgPSAxLCBjb2w9IiNmYmFlM2IiKSArDQogICAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSA0LjQiKSArDQogICAjIGNvb3JkX2VxdWFsKHlsaW0gPSBjKG1pbihwMTEkbGF0KSwgbWF4KHAxMSRsYXQpKSwgeGxpbT0gYyhtaW4ocDExJGxvbmcpLCBtYXgocDExJGxvbmcpKSkgKw0KICAgIHRoZW1lX2J3KCkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGE0XzQucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCkNhbGN1bGF0ZSBWSXMNCg0KDQpgYGB7cn0NCg0KcDQxLlZJcyA8LSBzcGVjdHJhbEluZGljZXMoVFRDMDgyMjZfbW9kaWZpZWQuc3RhY2tfcDQxLCBncmVlbiA9IDMsIHJlZD0yLCBuaXIgPTEsIGluZGljZXM9YygiTkRWSSIsICJNU0FWSTIiLCAiR05EVkkiKSkNCmJyZWFrcyA8LSBzZXEoMCwgMSwgYnk9MC4wMSkNCg0KcGxvdChwNDEuVklzKQ0KYGBgDQoNCmBgYHtyfQ0KDQpwNDIuVklzIDwtIHNwZWN0cmFsSW5kaWNlcyhUVEMwODIyNl9tb2RpZmllZC5zdGFja19wNDIsIGdyZWVuID0gMywgcmVkPTIsIG5pciA9MSwgaW5kaWNlcz1jKCJORFZJIiwgIk1TQVZJMiIsICJHTkRWSSIpKQ0KYnJlYWtzIDwtIHNlcSgwLCAxLCBieT0wLjAxKQ0KDQpwbG90KHA0Mi5WSXMpDQoNCmBgYA0KDQpgYGB7cn0NCg0KcDQzLlZJcyA8LSBzcGVjdHJhbEluZGljZXMoVFRDMDgzMzVfbW9kaWZpZWQuc3RhY2tfcDQzLCBncmVlbiA9IDMsIHJlZD0yLCBuaXIgPTEsIGluZGljZXM9YygiTkRWSSIsICJNU0FWSTIiLCAiR05EVkkiKSkNCmJyZWFrcyA8LSBzZXEoMCwgMSwgYnk9MC4wMSkNCg0KcGxvdChwNDMuVklzKQ0KYGBgDQoNCmBgYHtyfQ0KDQpwNDQuVklzIDwtIHNwZWN0cmFsSW5kaWNlcyhUVEMwODMzNV9tb2RpZmllZC5zdGFja19wNDQsIGdyZWVuID0gMywgcmVkPTIsIG5pciA9MSwgaW5kaWNlcz1jKCJORFZJIiwgIk1TQVZJMiIsICJHTkRWSSIpKQ0KYnJlYWtzIDwtIHNlcSgwLCAxLCBieT0wLjAxKQ0KDQpwbG90KHA0NC5WSXMpDQpgYGANCg0KUGxvdCBWSSBvbmUgYnkgb25lDQoNCiMjIyBORFZJIFBhcmNlbGEgNC4xDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0MS5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDQuMSIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQpBbmQgc2F2ZQ0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8xX05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQojIyMgTVNBVkkyIFBhcmNlbGEgNC4xDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0MS5WSXMkTVNBVkkyLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgNC4xIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCkFuZCBzYXZlDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGE0XzFfTVNBVkkyLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KIyMjIEdORFZJIFBhcmNlbGEgNC4xDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0MS5WSXMkR05EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSA0LjEiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfMV9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KDQoNCiMjIyBORFZJIFBhcmNlbGEgNC4yDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0Mi5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9ICJQYXJjZWxhIDQuMiIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQpBbmQgc2F2ZQ0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8yX05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQojIyMgTVNBVkkyIFBhcmNlbGEgNC4yDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0Mi5WSXMkTVNBVkkyLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0gIlBhcmNlbGEgNC4yIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCkFuZCBzYXZlDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGE0XzJfTVNBVkkyLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KIyMjIEdORFZJIFBhcmNlbGEgNC4yDQoNCmBgYHtyfQ0KY29scyA8LSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ5ZWxsb3ciLCAibGlnaHRncmVlbiIpKShsZW5ndGgoYnJlYWtzKS0xKQ0KZ2dSKHA0Mi5WSXMkR05EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSAiUGFyY2VsYSA0LjIiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfMl9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KDQojIyMgQWdhaW4gd2l0aCBwNC4zDQoNCmBgYHtyfQ0KcDQzLlZJcyA8LSBzcGVjdHJhbEluZGljZXMoVFRDMDgzMzVfbW9kaWZpZWQuc3RhY2tfcDQzLCBncmVlbiA9IDMsIHJlZD0yLCBuaXIgPTEsIGluZGljZXM9YygiTkRWSSIsICJNU0FWSTIiLCAiR05EVkkiKSkNCmJyZWFrcyA8LSBzZXEoMCwgMSwgYnk9MC4wMSkNCg0KcGxvdChwNDMuVklzKQ0KYGBgDQoNCg0KDQojIyMgTkRWSSAgUGFyY2VsYSA0LjMNCg0KYGBge3J9DQpnZ1IocDQzLlZJcyRORFZJLCBnZW9tX3Jhc3RlciA9IFRSVUUpICsNCiAgbGFicyh4PSIiLCB5PSIiLCB0aXRsZT0iUGFyY2VsYSA0LjMiKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9Y29scywgIG5hLnZhbHVlPU5BKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIiwgdmp1c3Q9MSwgaGp1c3QgPSAwLjUpKSAgIyBtYWtlIHRpdGxlIGJvbGQgYW5kIGFkZCBzcGFjDQoNCmBgYA0KDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGE0XzNfTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyMjIE1TQVZJMiBQYXJjZWxhIDQuMw0KDQpgYGB7cn0NCmdnUihwNDMuVklzJE1TQVZJMiwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC4zIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KDQpTYXZlDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL3BhcmNlbGE0XzNfTVNBVkkyLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQojIyMgR05EVkkgUGFyY2VsYSA0LjMNCg0KYGBge3J9DQpnZ1IocDQzLlZJcyRHTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC4zIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KU2F2ZQ0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8zX0dORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KZm9vDQoNCg0KIyMjIEFnYWluIHdpdGggcDQuMw0KDQpgYGB7cn0NCnA0My5WSXMgPC0gc3BlY3RyYWxJbmRpY2VzKFRUQzA4MzM1X21vZGlmaWVkLnN0YWNrX3A0MywgZ3JlZW4gPSAzLCByZWQ9MiwgbmlyID0xLCBpbmRpY2VzPWMoIk5EVkkiLCAiTVNBVkkyIiwgIkdORFZJIikpDQpicmVha3MgPC0gc2VxKDAsIDEsIGJ5PTAuMDEpDQoNCnBsb3QocDQzLlZJcykNCmBgYA0KDQoNCg0KIyMjIE5EVkkgIFBhcmNlbGEgNC4zDQoNCmBgYHtyfQ0KZ2dSKHA0My5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC4zIikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8zX05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCiMjIyBNU0FWSTIgUGFyY2VsYSA0LjMNCg0KYGBge3J9DQpnZ1IocDQzLlZJcyRNU0FWSTIsIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuMyIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNCg0KU2F2ZQ0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF8zX01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyMjIEdORFZJIFBhcmNlbGEgNC4zDQoNCmBgYHtyfQ0KZ2dSKHA0My5WSXMkR05EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuMyIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNClNhdmUNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfM19HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyMjIEFnYWluIHdpdGggcDQuNA0KDQpgYGB7cn0NCnA0NC5WSXMgPC0gc3BlY3RyYWxJbmRpY2VzKFRUQzA4MzM1X21vZGlmaWVkLnN0YWNrX3A0NCwgZ3JlZW4gPSAzLCByZWQ9MiwgbmlyID0xLCBpbmRpY2VzPWMoIk5EVkkiLCAiTVNBVkkyIiwgIkdORFZJIikpDQpicmVha3MgPC0gc2VxKDAsIDEsIGJ5PTAuMDEpDQoNCnBsb3QocDQzLlZJcykNCmBgYA0KDQoNCg0KIyMjIE5EVkkgIFBhcmNlbGEgNC40DQoNCmBgYHtyfQ0KZ2dSKHA0NC5WSXMkTkRWSSwgZ2VvbV9yYXN0ZXIgPSBUUlVFKSArDQogIGxhYnMoeD0iIiwgeT0iIiwgdGl0bGU9IlBhcmNlbGEgNC40IikgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPWNvbHMsICBuYS52YWx1ZT1OQSkgKyANCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIsIHZqdXN0PTEsIGhqdXN0ID0gMC41KSkgICMgbWFrZSB0aXRsZSBib2xkIGFuZCBhZGQgc3BhYw0KDQpgYGANCg0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF80X05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQoNCiMjIyBNU0FWSTIgUGFyY2VsYSA0LjQNCg0KYGBge3J9DQpnZ1IocDQ0LlZJcyRNU0FWSTIsIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuNCIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNCg0KU2F2ZQ0KDQpgYGB7cn0NCmdnc2F2ZSgiZmlndXJlcy9wYXJjZWxhNF80X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyMjIEdORFZJIFBhcmNlbGEgNC40DQoNCmBgYHtyfQ0KZ2dSKHA0NC5WSXMkR05EVkksIGdlb21fcmFzdGVyID0gVFJVRSkgKw0KICBsYWJzKHg9IiIsIHk9IiIsIHRpdGxlPSJQYXJjZWxhIDQuNCIpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz1jb2xzLCAgbmEudmFsdWU9TkEpICsgDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGxpbmVoZWlnaHQ9LjgsIGZhY2U9ImJvbGQiLCB2anVzdD0xLCBoanVzdCA9IDAuNSkpICAjIG1ha2UgdGl0bGUgYm9sZCBhbmQgYWRkIHNwYWMNCg0KYGBgDQoNClNhdmUNCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvcGFyY2VsYTRfNF9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCkJpbmQgaW5kaWNlcyBpbiBhIHdob2xlIGRhdGFmcmFtZQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBseXIpICMgVG9vbHMgZm9yIFNwbGl0dGluZywgQXBwbHlpbmcgYW5kIENvbWJpbmluZyBEYXRhDQoNCnJhc3Rlcl90b19kZiA8LSBmdW5jdGlvbih4KSB7DQogIHN0YWNrKGFzLmRhdGEuZnJhbWUoeCkpDQp9ICMgY29udmVydCByYXN0ZXIgdG8gZGF0YWZyYW1lDQoNCg0KbDwtIGxpc3QocDQxID0gcDQxLlZJcywgcDQyID0gcDQyLlZJcywgcDQzID0gcDQzLlZJcywgcDQ0ID0gcDQ0LlZJcykNCg0KbC5kZiA8LSBsYXBwbHkoWCA9IGwsIEZVTiA9IHJhc3Rlcl90b19kZikgIyBsaXN0IG9mIGRhdGEgZnJhbWVzDQoNCg0KbC5kZi5WSXMgPC0gbGRwbHkobC5kZiAscmJpbmQpICMgU3BsaXQgbGlzdCwgYXBwbHkgZnVuY3Rpb24sIGFuZCByZXR1cm4gcmVzdWx0cyBpbiBhIGRhdGEgZnJhbWUuDQoNCg0KYGBgDQoNCg0KUGxvdCBORFZJIGJveC1wbG90DQoNCmBgYHtyfQ0KbC5kZi5WSXMuTkRWSSA8LSAgc3Vic2V0KGwuZGYuVklzLCBpbmQgPT0gIk5EVkkiICkNCmdncGxvdChsLmRmLlZJcy5ORFZJKSArIA0KICBnZW9tX2JveHBsb3QoYWVzKHggPSAuaWQsIHkgPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArDQogIGZhY2V0X2dyaWQoLiB+IGluZCkgKw0KICB0aGVtZV9idygpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvYm94cGxvdF9wNDFfcDQyX3A0M19wNDRfTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNClBsb3QgTVNBVkkyIGJveC1wbG90DQoNCg0KYGBge3J9DQpsLmRmLlZJcy5NU0FWSTIgPC0gIHN1YnNldChsLmRmLlZJcywgaW5kID09ICJNU0FWSTIiICkNCg0KZ2dwbG90KGwuZGYuVklzLk1TQVZJMikgKyANCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gLmlkLCB5ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKw0KICBmYWNldF9ncmlkKC4gfiBpbmQpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2JveHBsb3RfcDQxX3A0Ml9wNDNfcDQ0X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNClBsb3QgR05EVkkgYm94LXBsb3QNCg0KDQpgYGB7cn0NCmwuZGYuVklzLkdORFZJIDwtICBzdWJzZXQobC5kZi5WSXMsIGluZCA9PSAiR05EVkkiICkNCmdncGxvdChsLmRmLlZJcy5HTkRWSSkgKyANCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gLmlkLCB5ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKw0KICBmYWNldF9ncmlkKC4gfiBpbmQpICsNCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2JveHBsb3RfcDQxX3A0Ml9wNDNfcDQ0X0dORFZJLnBuZyIsIA0KIHBsb3QgPSBsYXN0X3Bsb3QoKSwgIyBvciBnaXZlIGdncGxvdCBvYmplY3QgbmFtZSBhcyBpbiBteVBsb3QsDQogd2lkdGggPSA1LCBoZWlnaHQgPSA1LCANCiB1bml0cyA9ICJpbiIsICMgb3RoZXIgb3B0aW9ucyBjKCJpbiIsICJjbSIsICJtbSIpLCANCiBkcGkgPSAzMDApDQpgYGANCg0KDQpQbG90IE5EVkksIEdORFZJIE1TQVZJMiBoaXN0b2dyYW0NCg0KYGBge3J9DQoNCmwuZGYuVklzLk5EVkkkdGl0bGUgPC0gIk5EVkkiICMgZmFrZQ0KDQpnZ3Bsb3QobC5kZi5WSXMuTkRWSSwgYWVzKHggPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArIA0KICBnZW9tX2ZyZXFwb2x5KGFlcyggeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGJpbndpZHRoID0gMC4wMDUpICsNCiAgZmFjZXRfd3JhcCh+dGl0bGUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsNCiAgeWxhYigicmVsYXRpdmUgZnJlcXVlbmNpZXMiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvaGlzdG9fcDQxX3A0Ml9wNDNfcDQ0X05EVkkucG5nIiwgDQogcGxvdCA9IGxhc3RfcGxvdCgpLCAjIG9yIGdpdmUgZ2dwbG90IG9iamVjdCBuYW1lIGFzIGluIG15UGxvdCwNCiB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIA0KIHVuaXRzID0gImluIiwgIyBvdGhlciBvcHRpb25zIGMoImluIiwgImNtIiwgIm1tIiksIA0KIGRwaSA9IDMwMCkNCmBgYA0KDQpgYGB7cn0NCg0KbC5kZi5WSXMuTVNBVkkyJHRpdGxlID0gIk1TQVZJMiINCg0KZ2dwbG90KGwuZGYuVklzLk1TQVZJMiwgYWVzKHggPSB2YWx1ZXMsIGNvbG91cj0uaWQpKSArIA0KICBnZW9tX2ZyZXFwb2x5KGFlcyggeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGJpbndpZHRoID0gMC4wMDUpICsNCiAgZmFjZXRfd3JhcCh+dGl0bGUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsNCiAgeWxhYigicmVsYXRpdmUgZnJlcXVlbmNpZXMiKSArIA0KICB0aGVtZV9idygpDQpgYGANCg0KYGBge3J9DQpnZ3NhdmUoImZpZ3VyZXMvaGlzdG9fcDQxX3A0Ml9wNDNfcDQ0X01TQVZJMi5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCmBgYHtyfQ0KbC5kZi5WSXMuR05EVkkkdGl0bGUgPC0gIkdORFZJIiAjIGZha2UNCg0KDQpnZ3Bsb3QobC5kZi5WSXMuR05EVkksIGFlcyh4ID0gdmFsdWVzLCBjb2xvdXI9LmlkKSkgKyANCiAgZ2VvbV9mcmVxcG9seShhZXMoIHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBiaW53aWR0aCA9IDAuMDA1KSArDQogIGZhY2V0X3dyYXAofnRpdGxlKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArDQogIHlsYWIoInJlbGF0aXZlIGZyZXF1ZW5jaWVzIikgKyANCiAgdGhlbWVfYncoKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dzYXZlKCJmaWd1cmVzL2hpc3RvX3A0MV9wNDJfcDQzX3A0NF9HTkRWSS5wbmciLCANCiBwbG90ID0gbGFzdF9wbG90KCksICMgb3IgZ2l2ZSBnZ3Bsb3Qgb2JqZWN0IG5hbWUgYXMgaW4gbXlQbG90LA0KIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgDQogdW5pdHMgPSAiaW4iLCAjIG90aGVyIG9wdGlvbnMgYygiaW4iLCAiY20iLCAibW0iKSwgDQogZHBpID0gMzAwKQ0KYGBgDQoNCg0KIyBBbmFseXNpcw0KDQpgYGB7cn0NCmxpYnJhcnkoJ2RwbHlyJykNCmwuZGYuVklzICU+JSBncm91cF9ieShpbmQpICU+JSBzdW1tYXJpc2VfYXQoInZhbHVlcyIsIGZ1bnMobWVhbiwgbWVkaWFuLCBtYXgsIG1pbixzZCksIG5hLnJtID0gVFJVRSkNCg0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeSgnZHBseXInKQ0KbC5kZi5WSXMgJT4lIGdyb3VwX2J5KGluZCwgLmlkKSAlPiUgc3VtbWFyaXNlX2F0KCJ2YWx1ZXMiLCBmdW5zKG1lYW4sIG1lZGlhbiwgbWF4LCBtaW4sc2QpLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KYGBge3J9DQpzYXZlUkRTKGwuZGYuVklzLCBmaWxlID0gIlZJUDQucmRzIikNCmBgYA0KDQoNCmBgYHtyfQ0KIyBzYXZlIHA0MSBsYXllcnMNCndyaXRlUmFzdGVyKHN0YWNrKHA0MS5WSXMpLCBwYXN0ZSgicDQxXyIsIG5hbWVzKHA0MS5WSXMpLCBzZXAgPSAnJyksIGJ5bGF5ZXI9VFJVRSwgZm9ybWF0PSdHVGlmZicpDQp3cml0ZVJhc3RlcihzdGFjayhwNDIuVklzKSwgcGFzdGUoInA0Ml8iLCBuYW1lcyhwNDIuVklzKSwgc2VwID0gJycpLCBieWxheWVyPVRSVUUsIGZvcm1hdD0nR1RpZmYnKQ0Kd3JpdGVSYXN0ZXIoc3RhY2socDQzLlZJcyksIHBhc3RlKCJwNDNfIiwgbmFtZXMocDQzLlZJcyksIHNlcCA9ICcnKSwgYnlsYXllcj1UUlVFLCBmb3JtYXQ9J0dUaWZmJykNCndyaXRlUmFzdGVyKHN0YWNrKHA0NC5WSXMpLCBwYXN0ZSgicDQ0XyIsIG5hbWVzKHA0NC5WSXMpLCBzZXAgPSAnJyksIGJ5bGF5ZXI9VFJVRSwgZm9ybWF0PSdHVGlmZicpDQoNCmBgYA0KDQo=